import Box2D.b2 as b2
import pyglet
from pyglet.image import Animation, AnimationFrame

import activations
from camera import pixels_to_world
from debug import msg
import entity
import resources


class Contraption(entity.Entity):
    """
    Entity that handles interactions between electricals and
    non-electricals (portals).
    """
    def __init__(self, mode, _id, on_activate, on_deactivate=[]):
        super(Contraption, self).__init__(mode)

        self._id = _id
        self.on_activate = on_activate
        self.on_deactivate = on_deactivate

    def activate(self):
        for f in self.on_activate:
            f()

    def deactivate(self):
        for f in self.on_deactivate:
            f()

class Button(entity.StaticSprite):
    """
    Entity that is activates when pressed, and deactivates when
    depressed.
    """
    def __init__(self, mode, _id, start_configurations):

        self._id = _id

        self.mode = mode

        # The relative position of the image anchor. (0.5, 0.5) gives
        # a centralized anchorpoint.
        anchor = (0.5, 0)

        # Import imagegrid
        self.image = resources.image_grid("data/img/button.png", anchor, (1, 3))

        # Create a dictionary with animations.
        self.animations = {"up": Animation([AnimationFrame(self.image[1],0.05),
                                            AnimationFrame(self.image[0],None)]),
                           "down": Animation([AnimationFrame(self.image[1],0.02),
                                              AnimationFrame(self.image[2],None)]),
                           }

        ((x,y),rot) = start_configurations
        super(Button, self).__init__(mode, self.image[0], anchor=anchor,
                                     x=x, y=y, rot=rot, e_type="button")

        for f in self.body.fixtures:
            f.sensor = True

        self.pressed = False

        self.contact_count = 0

    def activate(self):
        # Animate
        self.sprite.image = self.animations["down"]

        # Propagate event
        for o in self.mode.level.electric_connections.get_ordered(self._id):
            o.activate()

        # Set flag
        self.pressed = True

    def deactivate(self):
        # Animate
        self.sprite.image = self.animations["up"]

        # Propagate event
        for o in self.mode.level.electric_connections.get_ordered(self._id):
            o.deactivate()

        # Set flag
        self.pressed = False

    def contact_increase(self):
        self.contact_count += 1

    def contact_decrease(self):
        self.contact_count -= 1

    def update(self, dt):
        super(Button, self).update(dt)

        if self.pressed and self.contact_count is 0:
            self.deactivate()

        if not self.pressed and self.contact_count is not 0:
            self.activate()

        if self.contact_count < 0:
            msg ("FIXME: box.contact_count < 0 (_id = %s)." % self._id)
            self.contact_count = 0


class Door(entity.StaticSprite):
    """
    Entity that blocks passage. Opens when activated, closes when
    deactivated (in case of multiple consecutive activations it closes
    when number of deactivations equal number of activations.
    """
    def __init__(self, mode, _id, start_configurations, start_closed=True):

        # The relative position of the image anchor. (0.5, 0.5) gives
        # a centralized anchorpoint.
        # Here: lower right corner.
        self.anchor = (1, 0)

        # Import imagegrid
        self.image = resources.image_grid("data/img/door.png", self.anchor, (1, 6))

        # Create a dictionary with animations.
        self.animations = {"close": Animation([AnimationFrame(self.image[4],
                                                              0.03),
                                               AnimationFrame(self.image[3],
                                                              0.03),
                                               AnimationFrame(self.image[2],
                                                              0.03),
                                               AnimationFrame(self.image[1],
                                                              0.03),
                                               AnimationFrame(self.image[0],
                                                              None)]),
                           "open": Animation([AnimationFrame(self.image[1],
                                                             0.05),
                                              AnimationFrame(self.image[2],
                                                             0.05),
                                              AnimationFrame(self.image[3],
                                                             0.05),
                                              AnimationFrame(self.image[4],
                                                             0.05),
                                              AnimationFrame(self.image[5],
                                                             None)]),
                           }

        ((x, y), rot) = start_configurations

        self.activated = False
        self.activate_counter = 0

        super(Door, self).__init__(
            mode, self.image[0], anchor=self.anchor,
            x=x, y=y, rot=rot,
            e_type="door")


        self._id = _id

    def activate(self):
        """
        Activates (opens) the door.
        """
        if not self.activated:
            # Animate
            self.sprite.image = self.animations["open"]

            # Become passable
            for f in self.body.fixtures:
                f.sensor = True

            # Update flag
            self.activated = True

        self.activate_counter += 1

    def deactivate(self):
        """
        Deactivates (closes) the door.
        """
        self.activate_counter -= 1

        if self.activate_counter < 0:
            msg("FIXME: door.activate_counter < 0 (_id = %s)." % self._id)

        if self.activate_counter is 0:
            # Animate
            self.sprite.image = self.animations["close"]

            # Become impassable
            for f in self.body.fixtures:
                f.sensor = False

            # Update flag
            self.activated = False

    def update(self, dt):
        super(Door, self).update(dt)

        if ((self.activate_counter is 0 and self.activated) or
            (self.activate_counter > 0 and not self.activated)):
            msg("FIXME: door (_id = %s) activated" % self._id)

class Lever(entity.StaticSprite):
    """
    Entity activates or deactivates on interaction.
    """
    def __init__(self, mode, _id, start_configurations):

        self._id = _id

        # The relative position of the image anchor. (0.5, 0.5) gives
        # a centralized anchorpoint.
        anchor = (0.5, 0)

        # Import imagegrid
        self.image = resources.image_grid("data/img/lever.png", anchor, (1, 4))

        # Create a dictionary with animations.
        self.animations = {"left": Animation([AnimationFrame(self.image[1],0.05),
                                              AnimationFrame(self.image[0],None)]),
                           "right": Animation([AnimationFrame(self.image[2],0.05),
                                               AnimationFrame(self.image[3],None)]),
                           }

        ((x,y),self.rotation) = start_configurations
        super(Lever, self).__init__(mode, self.image[0], anchor=anchor,
                                    x=x, y=y, rot=self.rotation, e_type="lever")

        self.activated = False

        for f in self.body.fixtures:
            f.sensor = True

    def interact(self):
        pyglet.resource.media('clonk.mp3', streaming=False).play()
        if self.activated:
            self.deactivate()
        else:
            self.activate()

    def activate(self):
        # Animate
        self.sprite.image = self.animations["right"]

        # Propagate event
        for o in self.mode.level.electric_connections.get_ordered(self._id):
            o.activate()

        # Set flag
        self.activated = True

    def deactivate(self):
        # Animate
        self.sprite.image = self.animations["left"]

        # Propagate event
        for o in self.mode.level.electric_connections.get_ordered(self._id):
            o.deactivate()

        # Set flag
        self.activated = False



